/*
 * DCChannel.java
 *
 * Created on 30 de Junho de 2005, 14:39
 */

package jhub;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.*;
import jhub.text.ActiveSearchMessage;
import jhub.text.ConnectToMeMessage;

import jhub.text.DCRawCommand;
import jhub.text.GetInfoMessage;
import jhub.text.KeyMessage;
import jhub.text.KickMessage;
import jhub.text.MyINFOMessage;
import jhub.text.MyPassMessage;
import jhub.text.OpForceMoveMessage;
import jhub.text.PassiveSearchMessage;
import jhub.text.PassiveSearchResultMessage;
import jhub.text.PrivateChatMessage;
import jhub.text.PublicChatMessage;
import jhub.text.ValidateNickMessage;
import jhub.text.VersionMessage;
import org.apache.log4j.Logger;
/**
 *
 * @author  botelhodaniel
 */
public class DCChannel {
    
    public static Logger logger = Logger.getLogger(DCChannel.class);
    
    protected LinkedList<DCRawCommand> queue;
    
    protected Socket socket;
    private DCBufferedReader in;
    private DataOutputStream out;
    private String ip;
    private int port;
    
    /** Creates a new instance of DCChannel
     * @throws IOException */
    protected DCChannel(Socket socket) throws IOException {
        this.socket = socket;
        ip = socket.getInetAddress().getHostAddress();
        port = socket.getPort();
        queue = new LinkedList<DCRawCommand>();
        
        in = new DCBufferedReader(new InputStreamReader(socket.getInputStream()));
        out = new DataOutputStream(socket.getOutputStream());
    }
    
    public DCRawCommand read() throws IOException{
        if(!queue.isEmpty())
            return queue.removeFirst();
        
        DCStringTokenizer st = null;
        
        do{
            st = new DCStringTokenizer(in.readLine());
        } while (st.countTokens() < 1);
        
        while (st.hasMoreTokens()){
            String raw = st.nextToken();
            DCRawCommand command;
            
            try {
                if(raw.startsWith(DCProtocol.PUBLIC_CHAT_ID)){
                    command = new PublicChatMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.MYINFO_ID)){
                    command = new MyINFOMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.GETINFO_ID)){
                    
                    command = new GetInfoMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.VERSION_ID)){
                    
                    command =new VersionMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.CONNECTTOME_ID)){
                    command =new ConnectToMeMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.PRIVATE_CHAT_ID)){
                    
                    command = new PrivateChatMessage( raw ) ;
                    
                }else if(raw.startsWith(DCProtocol.PASSIVE_SEARCH_RESULT_ID)){
                    
                    command = new PassiveSearchResultMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.PASSIVE_SEARCH_ID)){
                    
                    command = new PassiveSearchMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.ACTIVE_SEARCH_ID)){
                    
                    command = new ActiveSearchMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.VALIDATE_NICK_ID)){
                    
                    command = new ValidateNickMessage(raw);
                    
                }else if(raw.startsWith(DCProtocol.VERSION_ID)){
                    
                    command = new VersionMessage(raw);
                }else if(raw.startsWith(DCProtocol.MYPASS_ID)){
                    
                    command = new MyPassMessage(raw);
                }else if(raw.startsWith(DCProtocol.KEY_ID)){
                    command = new KeyMessage(raw);
                }else if(raw.startsWith(DCProtocol.KICK_ID)){
                    command = new KickMessage(raw);
                }else if(raw.startsWith(DCProtocol.FORCEMOVE_ID)){
                    command = new OpForceMoveMessage(raw);
                }else
                    command = new DCRawCommand(raw);
            } catch (ParseException ex) {
                ex.printStackTrace();
                command = new DCRawCommand(raw);
            }
            
            queue.addLast(command);
            //System.out.println(command);
        }
        return queue.removeFirst();
        
    }
    
    protected int write(DCRawCommand raw) throws UnsupportedEncodingException, IOException{
        //logger.info("<"+new SimpleDateFormat("yyyy-MM-dd kk:mm:ss").format(raw.getTimeStamp())+">("+ip+":"+port+"),H->C:"+raw);
        out.write(raw.getBytes());
        return raw.getBytes().length;
    }
    
    public boolean isClosed(){
        return socket.isClosed();
    }
    
    public void close() throws IOException{
        socket.close();
    }
    
    public boolean available() {
        // TODO Auto-generated method stub
        return !socket.isOutputShutdown() /*+ !socket.close()*/;
    }
    
    /**
     * @return Returns the ip.
     */
    public String getIp() {
        return ip;
    }
    
    /**
     * @return Returns the port.
     */
    public int getPort() {
        return port;
    }
    
}
